package org.yaac.client.ui;

import static com.google.common.collect.Lists.newLinkedList;

import java.util.LinkedList;
import java.util.List;

import javax.inject.Inject;

import org.yaac.client.activity.EditorActivity;
import org.yaac.client.ui.EditorEntityNotFoundPanel.CreateButtonHandler;
import org.yaac.client.widget.ToggleButtonGroup;
import org.yaac.client.widget.ToggleButtonGroup.SelectionChangeListener;
import org.yaac.shared.editor.EntityHierarchy;
import org.yaac.shared.editor.EntityInfo;
import org.yaac.shared.editor.EntityUpdateInfo;
import org.yaac.shared.property.KeyInfo;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DeckLayoutPanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.ToggleButton;
import com.google.gwt.user.client.ui.Widget;

/**
 * @author Max Zhu (thebbsky@gmail.com)
 *
 */
public class EditorViewImpl extends Composite implements EditorView {

	private static EditorViewUiBinder uiBinder = GWT.create(EditorViewUiBinder.class);

	@UiTemplate("EditorView.ui.xml")
	interface EditorViewUiBinder extends UiBinder<Widget, EditorViewImpl> {
	}

	@UiField
	TextBox keyStringTxt;
	
	private String keyString;
	
	@UiField
	FlowPanel switchControlPanel;
	
	@UiField
	Button saveBtn;
	
	@UiField
	Button deleteBtn;
	
	@UiField
	Button copyToNewBtn;
	
	@UiField
	DeckLayoutPanel mainDeck;
	
	private EditorActivity listener;
	
	// internal status
	private boolean waitingForFirstClick;
	
	private final EditorPropertyManager editorManager;
	
	@Inject
	EditorViewImpl(EditorPropertyManager editorManager) {
		this.editorManager = editorManager;
		
		initWidget(uiBinder.createAndBindUi(this));
		
		mainDeck.setAnimationDuration(500);
		
		this.waitingForFirstClick = true;
	}

	@Override
	public void setPresenter(EditorActivity listener) {
		this.listener = listener;
	}

	@UiHandler("keyStringTxt")
	void onKeyStringTxtClick(ClickEvent event) {
		if (waitingForFirstClick) {
			keyStringTxt.setText("");
			waitingForFirstClick = false;
		}
	}
	
	@UiHandler("keyStringTxt")
	void onKeyStringTxtKeyPress(KeyPressEvent event) {
		char key = event.getCharCode();
		if (KeyCodes.KEY_ENTER == key) {
			keyString = keyStringTxt.getText().trim();
			listener.startLoad(keyString);
		}
	}

	@UiHandler("saveBtn")
	void onSaveBtnClick(ClickEvent event) {
		List<EntityUpdateInfo> changes = newLinkedList();
		
		for (Widget w : this.mainDeck) {
			if (w instanceof EditorEntityPanel) {	// can be label as well, when the entity doesn't actualy exist
				EditorEntityPanel editor = ((EditorEntityPanel) w);
				EntityUpdateInfo updateInfo = editor.updatedInfo();
				
				if (updateInfo != null) {
					changes.add(updateInfo);
				}
			}
		}
		
		if (changes.isEmpty()) {
			Window.alert("Nothing changed");
		} else {
			this.listener.update(changes);
		}
	}
	
	@UiHandler("deleteBtn")
	void onDeleteBtnClick(ClickEvent event) {
		Widget w = this.mainDeck.getVisibleWidget();
		
		if (w instanceof EditorEntityPanel) {
			if (Window.confirm("Are you sure you want to delete this entity?")) {
				KeyInfo key = ((EditorEntityPanel) w).getOrigKey();
				this.listener.delete(key);
			}
		}
	}
	
	@UiHandler("copyToNewBtn")
	void onCopyToNewBtnClick(ClickEvent event) {
		Widget w = this.mainDeck.getVisibleWidget();
		
		if (w instanceof EditorEntityPanel) {
			if (Window.confirm("Are you sure you want to copy to new entity? Unsaved changes will be discarded")) {
				KeyInfo key = ((EditorEntityPanel) w).getOrigKey();
				this.listener.copyToNew(key);
			}
		}
	}
	
	@Override
	public void setKeyString(String keyString) {
		this.keyString = keyString;
		this.keyStringTxt.setText(keyString);
		this.waitingForFirstClick = false;
	}
	
	private ToggleButtonGroup<KeyInfo> btnGroup;	
	private List<KeyInfo> keys;
	
	@Override
	public void onDataReady(EntityHierarchy hierarchy) {
		// step 1 : clear previous entity hierarchy
		btnGroup = new ToggleButtonGroup<KeyInfo>();
		keys = new LinkedList<KeyInfo>();
		switchControlPanel.clear();
		mainDeck.clear();
		
		// step 2 : render UIs
		KeyInfo key = hierarchy.getKey();
		
		while (key != null) {
			keys.add(0, key);
			
			// render buttons on control panel
			ToggleButton btn = new ToggleButton(key.asSingleNodeDesc());
			btn.getElement().getStyle().setFloat(Style.Float.LEFT);
			
			// parent always goes the first
			switchControlPanel.insert(btn, 0);
			btnGroup.addButton(key, btn);

			// render contents on main deck
			final KeyInfo thisKey = key;
			EntityInfo e = hierarchy.lookupAncester(key);
			Widget w = e != null ? new EditorEntityPanel(e, editorManager) : 
				new EditorEntityNotFoundPanel(
						new CreateButtonHandler() {
					@Override
					public void onButtonClick() {
						listener.create(thisKey);
					}
				});
			
			mainDeck.insert(w, 0);
			
			key = key.getParent();
		}
		
		// step 3 : subscribe selection change listener
		btnGroup.subscribe(new SelectionChangeListener<KeyInfo>() {
			@Override
			public void onSelect(KeyInfo selectedKey) {
				mainDeck.showWidget(keys.indexOf(selectedKey));
			}
		});
		
		// step 4 : select current entity as default
		btnGroup.select(hierarchy.getKey());
		mainDeck.showWidget(keys.indexOf(hierarchy.getKey()));
	}

	
	
	@Override
	public String getKeyString() {
		return this.keyString;
	}
}
